package karaokestrong.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;

import karaokestrong.excepcion.DAOExcepcion;
import karaokestrong.modelo.Cliente;
import karaokestrong.modelo.Local;
import karaokestrong.modelo.Reserva;
import karaokestrong.modelo.Sala;
import karaokestrong.util.ConexionBD;

public class ReservaDAO extends BaseDAO {

	public static boolean isNumeric(String str)
	{
		return str.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.
	}

	public int obtenerIDClientePorDNIOCorreo(String dniOCorreo) throws DAOExcepcion{
		int resp = 0;
		String query = "";		
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			if(isNumeric(dniOCorreo))
				query = "select idcliente from cliente where dni = ?";
			else
				query = "select idcliente from cliente where correo = ?";
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			if(isNumeric(dniOCorreo))
				stmt.setInt(1, Integer.parseInt(dniOCorreo));
			else
				stmt.setString(1, (String)dniOCorreo);

			rs = stmt.executeQuery();
			if (rs.next()) {
				resp = rs.getInt("idcliente");
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return resp;
	}

	public Collection<Sala> obtenerSalas() throws DAOExcepcion{
		String query = "select idsala, nombre from sala";
		Collection<Sala> c = new ArrayList<>();
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			rs = stmt.executeQuery();
			while (rs.next()) {				
				Sala sala = new Sala();
				sala.setIdsala(rs.getInt("idsala"));
				sala.setNombre(rs.getString("nombre"));
				c.add(sala);	
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return c;

	}

	public Collection<Cliente> obtenerClientes() throws DAOExcepcion{
		String query = "select idcliente, correo 'cliente' from cliente UNION select idcliente, dni 'cliente' from cliente";
		Collection<Cliente> c = new ArrayList<>();
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			rs = stmt.executeQuery();
			while (rs.next()) {

				Cliente cliente = new Cliente();
				cliente.setIdcliente(rs.getInt("idcliente"));
				cliente.setCorreoCliente(rs.getString("cliente"));
				c.add(cliente);	
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return c;

	}

	public void eliminar(int idReserva) throws DAOExcepcion {
		String query = "update reserva set elog=true where idreserva=?";
		Connection con = null;
		PreparedStatement stmt = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			stmt.setInt(1, idReserva);
			int i = stmt.executeUpdate();
			if (i != 1) {
				throw new SQLException("No se pudo eliminar");
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
	}

	public Reserva actualizar(Reserva vo) throws DAOExcepcion {
		String query = "update reserva set idcliente=?, fecha=?, descripcion=? where idreserva=?";
		Connection con = null;
		PreparedStatement stmt = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			stmt.setInt(1, vo.getCliente().getIdcliente());
			stmt.setTimestamp(2, vo.getFecha());
			stmt.setString(3, vo.getDescripcion());
			stmt.setInt(4, vo.getId());

			int i = stmt.executeUpdate();
			if (i != 1) {
				throw new SQLException("No se pudo actualizar");
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return vo;
	}
	public Reserva insertar(Reserva reserva) throws DAOExcepcion
	{
		String sqlQuery;
		sqlQuery = "INSERT INTO reserva(fecha,descripcion,elog,idsala,idcliente) VALUES (?,?,?,?,?)";
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(sqlQuery);
			stmt.setTimestamp(1, reserva.getFecha());
			stmt.setString(2, reserva.getDescripcion());
			stmt.setBoolean(3, false);
			stmt.setInt(4, reserva.getSala().getIdsala());
			stmt.setInt(5, reserva.getCliente().getIdcliente());
			int i = stmt.executeUpdate();
			if (i != 1) {
				throw new SQLException("No se pudo insertar");
			}

			// Obtener el ultimo id
			int id = 0;
			sqlQuery = "SELECT LAST_INSERT_ID()";
			stmt = con.prepareStatement(sqlQuery);
			rs = stmt.executeQuery();
			if (rs.next()) {
				id = rs.getInt(1);
			}
			reserva.setId(id);


		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return reserva;

	}
	public Reserva obtenerProductoPorId(int idReserva) throws DAOExcepcion {
		Reserva vo = new Reserva();
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String query = "select r.*, e.correo, s.nombre 'nombresala' from reserva r inner join cliente e on r.idcliente = e.idcliente inner join sala s on r.idsala = s.idsala where idreserva=? and r.elog = false";
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			stmt.setInt(1, idReserva);

			rs = stmt.executeQuery();
			if (rs.next()) {
				vo.setId(rs.getInt("idreserva"));
				vo.setFecha(rs.getTimestamp("fecha"));
				vo.setDescripcion(rs.getString("descripcion"));
				Sala sala = new Sala();
				sala.setIdsala(rs.getInt("idsala"));
				sala.setNombre(rs.getString("nombresala"));
				vo.setSala(sala);
				Cliente cliente = new Cliente();
				cliente.setIdcliente(rs.getInt("idcliente"));
				cliente.setCorreoCliente(rs.getString("correo"));
				vo.setCliente(cliente);
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return vo;
	}

	public Collection<Reserva> obtenerReservasPorCorreoOSala(String valor) throws DAOExcepcion{
		String query = "select r.idreserva, c.correo, c.dni, s.nombre, r.fecha, r.descripcion " + 
				"from reserva r "+ 
				"inner join cliente c on r.idcliente = c.idcliente " + 
				"inner join sala s on r.idsala = s.idsala " +
				"where (lower(c.correo) like lower(?) or lower(s.nombre) like lower(?)) and r.elog = false";
		Collection<Reserva> c = new ArrayList<>();
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			stmt.setString(1, "%" + valor + "%");
			stmt.setString(2, "%" + valor + "%");
			rs = stmt.executeQuery();
			while (rs.next()) {

				Reserva vo = new Reserva();
				vo.setId(rs.getInt("idreserva"));
				vo.setFecha(rs.getTimestamp("fecha"));
				vo.setDescripcion(rs.getString("descripcion"));
				
				Sala sala= new Sala();
				sala.setNombre(rs.getString("nombre"));
				vo.setSala(sala);
				
				Cliente cliente = new Cliente();
				cliente.setCorreoCliente(rs.getString("correo"));
				cliente.setDni(rs.getInt("dni"));
				vo.setCliente(cliente);
				
				c.add(vo);
			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return c;
	}

	public Collection<Reserva> listarReservaCliente() throws DAOExcepcion {
		String query = "select l.nombre as nlocal, s.nombre, r.fecha, r.descripcion from  local l, sala s, reserva r where l.idlocal = s.idlocal and s.idsala = r.idsala";

		Collection<Reserva> c = new ArrayList<Reserva>();
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			con = ConexionBD.obtenerConexion();
			stmt = con.prepareStatement(query);
			rs = stmt.executeQuery();
			while (rs.next()) {

				Reserva vo = new Reserva();
				Sala sala= new Sala();
				Local local = new Local();

				local.setNombre(rs.getString("nlocal"));
				sala.setLocal(local);
				vo.setSala(sala);

				sala.setNombre(rs.getString("nombre"));
				vo.setSala(sala);


				vo.setFecha(rs.getTimestamp("fecha"));
				vo.setDescripcion(rs.getString("descripcion"));
				c.add(vo);



			}
		} catch (SQLException e) {
			System.err.println(e.getMessage());
			throw new DAOExcepcion(e.getMessage());
		} finally {
			this.cerrarResultSet(rs);
			this.cerrarStatement(stmt);
			this.cerrarConexion(con);
		}
		return c;
	}

}
